﻿using System.Collections.Generic;
using System;

namespace Inovout.Models
{
    public class DataObjectSet<TModel> : HashSet<TModel>,IDataObjectSet<TModel>, Iesi.Collections.Generic.ISet<TModel>
    {
        public DataObjectSet() { }
        private Action<TModel> setOwner;
        public DataObjectSet(Action<TModel> setOwner)
        {
            this.setOwner = setOwner;
        }

        public new virtual bool Add(TModel item)
        {
            if (setOwner != null)
            {
                setOwner(item);
            }
            return base.Add(item);
        }
        public bool AddAll(ICollection<TModel> collection)
        {
            bool changed = false;
            foreach (TModel o in collection)
            {
                changed |= this.Add(o);
            }
            return changed;
        }
        public bool ContainsAll(ICollection<TModel> collection)
        {
            foreach (TModel o in collection)
            {
                if (!this.Contains(o))
                {
                    return false;
                }
            }
            return true;
        }

        public Iesi.Collections.Generic.ISet<TModel> ExclusiveOr(Iesi.Collections.Generic.ISet<TModel> a)
        {
            Iesi.Collections.Generic.ISet<TModel> resultSet = (Iesi.Collections.Generic.ISet<TModel>)this.Clone();
            foreach (TModel element in a)
            {
                if (resultSet.Contains(element))
                {
                    resultSet.Remove(element);
                }
                else
                {
                    resultSet.Add(element);
                }
            }
            return resultSet;
        }
        public Iesi.Collections.Generic.ISet<TModel> Intersect(Iesi.Collections.Generic.ISet<TModel> a)
        {
            Iesi.Collections.Generic.ISet<TModel> resultSet = (Iesi.Collections.Generic.ISet<TModel>)this.Clone();
            if (a != null)
            {
                resultSet.RetainAll(a);
            }
            else
            {
                resultSet.Clear();
            }
            return resultSet;
        }
        public bool IsEmpty
        {
            get { return this.Count == 0; }
        }
        public Iesi.Collections.Generic.ISet<TModel> Minus(Iesi.Collections.Generic.ISet<TModel> a)
        {
            Iesi.Collections.Generic.ISet<TModel> resultSet = (Iesi.Collections.Generic.ISet<TModel>)this.Clone();
            if (a != null)
            {
                resultSet.RemoveAll(a);
            }
            return resultSet;
        }
        public bool RemoveAll(ICollection<TModel> collection)
        {
            bool changed = false;
            foreach (TModel o in collection)
            {
                changed |= this.Remove(o);
            }
            return changed;
        }
        public bool RetainAll(ICollection<TModel> collection)
        {
            //We are going to build a set of elements to remove.
            ISet<TModel> removeSet = new DataObjectSet<TModel>();

            foreach (TModel o in this)
            {
                //If C does not contain O, then we need to remove O from our
                //set.  We can't do this while iterating through our set, so
                //we put it into RemoveSet for later.
                if (!collection.Contains(o))
                    removeSet.Add(o);
            }

            return this.RemoveAll(removeSet);
        }
        public Iesi.Collections.Generic.ISet<TModel> Union(Iesi.Collections.Generic.ISet<TModel> collection)
        {
            return (Iesi.Collections.Generic.ISet<TModel>)this.Union(collection);
        }
        public object Clone()
        {
            DataObjectSet<TModel> newSet = new DataObjectSet<TModel>();
            newSet.AddAll(this);
            return newSet;
        }
    }
}